siteapp.util.core.js ➔ hyphenate   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
"use strict";
2
3
// Core Siteapp Utilities, utilized in a number of places.
4
5
/**
6
 * Returns a boolean for RTL support
7
 */
8
function rtl() {
9
  return $('html').attr('dir') === 'rtl';
10
}
11
12
/**
13
 * returns a random base-36 uid with namespacing
14
 * @function
15
 * @param {Number} length - number of random base-36 digits desired. Increase for more random strings.
16
 * @param {String} namespace - name of plugin to be incorporated in uid, optional.
17
 * @default {String} '' - if no plugin name is provided, nothing is appended to the uid.
18
 * @returns {String} - unique id
19
 */
20
function GenerateUUID(length, namespace){
21
  length = length || 6;
22
  return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1) + (namespace ? `-${namespace}` : '');
23
}
24
25
/**
26
 * Vendor polyfill for 'transitionend'
27
 * 
28
 * @function
29
 * @param {jQuery} $elem
30
 * @returns {String}
31
 */
32
function transitionend($elem){
33
  var transitions = {
34
    'transition': 'transitionend',
35
    'WebkitTransition': 'webkitTransitionEnd',
36
    'MozTransition': 'transitionend',
37
    'OTransition': 'otransitionend'
38
  };
39
  var elem = document.createElement('div'),
40
      end;
41
42
  for (var t in transitions){
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
43
    if (typeof elem.style[t] !== 'undefined'){
44
      end = transitions[t];
45
    }
46
  }
47
  if(end){
48
    return end;
49
  }else{
50
    end = setTimeout(function(){
0 ignored issues
show
Unused Code introduced by
The assignment to variable end seems to be never used. Consider removing it.
Loading history...
51
      $elem.triggerHandler('transitionend', [$elem]);
52
    }, 1);
53
    return 'transitionend';
54
  }
55
}
56
57
/**
58
 * Overrides setters for some $object's properties(2secure).
59
 * So those properties can only be set, eg., when creating a new instance. 
60
 * 
61
 * This should try to prevent at least obvious direct hacking. #crossing-fingers
62
 * 
63
 * Either, the properties are locked silently:
64
 *   ```
65
 *   var obj = { a: 'x' };
66
 *   secureProperties( obj, ['a'] );
67
 *   
68
 *   obj.a = 'y';
69
 *   //console.//log(obj.a); // => "x"
70
 *   ```
71
 *   
72
 * or setting such property will throw an error:
73
 *   ```
74
 *   var obj = { a: 'x' };
75
 *   secureProperties( obj, ['a'] );
76
 *   
77
 *   obj.a = 'y' // => ERROR
78
 *   ```
79
 *   
80
 * @function
81
 * @access private
82
 * @param {object} $object - target object
83
 * @param {[string]} properties2secure - list of property keys to secure
84
 * @param {boolean} silent - wether to lock silently (true, default) or to throw an error (false) when setting the property
85
 * @returns {object} - the modified $object
86
 */
87
function secureProperties ( $object, properties2secure, silent ) {
88
	var 
89
		// action to call on object property setter access
90
	    $SECURITY_ALERT = function $SECURITY_ALERT () { 
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable $SECURITY_ALERT already seems to be declared on line 90. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
91
		    throw new Error('SECURITY ALERT: You are not allowed to do that in this context!'); 
92
		}
93
		
94
    ;
95
	let $_vault = {};
96
	
97
	for ( var idx in properties2secure ) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
98
		
99
		if ( $object.hasOwnProperty( properties2secure[idx] ) ) {
100
101
			let $prop  = properties2secure[idx];
102
			let $value = $object[ $prop ];
103
			
104
			// put property value into vault...
105
			$_vault[ $prop ] = $value;
106
			
107
			if (silent === false) {
108
				Object.defineProperty($object, $prop, {
109
					//
110
					// one method would be to override getter and setter...
111
					
112
					// map getter for property to vault...
113
					get : function () { return $_vault[$prop] },
114
					// ... and lock setter for property (hopefully), throwing error
115
				    set : $SECURITY_ALERT 
116
				});
117
			} else {
118
				Object.defineProperty($object, $prop, {
119
				    //
120
					// ...another method is to set the property's config:
121
					
122
				    // statically set the property value...
123
					value   : $_vault[ $prop ],
124
				    // ... and just disable writing access, to lock silently
125
					writable: false
126
				});
127
			}
128
		}
129
		
130
		
131
	}
132
	
133
	return $object;
134
}
135
136
/**
137
 * Shortcut and IE9 polyfill to get the name of a function/class instance
138
 * 
139
 * @function
140
 * @param {function} fn
141
 * @returns {string}
142
 */
143
function functionName(fn) {
144
    if (Function.prototype.name === undefined) {
145
        var funcNameRegex = /function\s([^(]{1,})\(/;
146
        var results = (funcNameRegex).exec((fn).toString());
147
        return (results && results.length > 1) ? results[1].trim() : "";
148
    }
149
    else if (fn.prototype === undefined) {
150
        return fn.constructor.name;
151
    }
152
    else {
153
        return fn.prototype.constructor.name;
154
    }
155
}
156
157
/**
158
 * Normalize/try to cast string value
159
 * 
160
 * @function
161
 * @param {mixed} str
162
 * @returns {boolean|number|string}
163
 */
164
function parseValue(str){
165
    if(/true/.test(str)) return true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
166
    else if(/false/.test(str)) return false;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
167
    else if(!isNaN(str * 1)) return parseFloat(str);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
168
    return str;
169
}
170
171
/**
172
 * Convert PascalCase to kebab-case
173
 * @see http://stackoverflow.com/a/8955580
174
 * 
175
 * @function
176
 * @param {string} str
177
 * @returns {string}
178
 */
179
function hyphenate(str) {
180
    return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
181
}
182
183
/**
184
 * Function for applying a debounce effect to a function call.
185
 * @function
186
 * @param {Function} func - Function to be called at end of timeout.
187
 * @param {Number} delay - Time in ms to delay the call of `func`.
188
 * @returns function
189
 */
190
function throttle(func, delay) {
191
    var timer = null;
192
193
    return function () {
194
        var context = this, args = arguments;
195
196
        if (timer === null) {
197
            timer = setTimeout(function () {
198
                func.apply(context, args);
199
                timer = null;
200
            }, delay);
201
        }
202
    };
203
}
204
205
export {
206
	rtl, 
207
	GenerateUUID, 
208
	transitionend, 
209
	secureProperties,
210
	functionName,
211
	parseValue,
212
	hyphenate,
213
	throttle
214
};
215
216